Apache |
您所在的位置:网站首页 › temporal temporary 区别 › Apache |
5万人关注的大数据成神之路,不来了解一下吗? 5万人关注的大数据成神之路,真的不来了解一下吗? 5万人关注的大数据成神之路,确定真的不来了解一下吗? 欢迎您关注《大数据成神之路》 ![]() 在《JOIN LATERAL》中提到了Temporal Table JOIN,本篇就向大家详细介绍什么是Temporal Table JOIN。 在ANSI-SQL 2011 中提出了Temporal 的概念,Oracle,SQLServer,DB2等大的数据库厂商也先后实现了这个标准。Temporal Table记录了历史上任何时间点所有的数据改动,Temporal Table的工作流程如下: ![]() 上图示意Temporal Table具有普通table的特性,有具体独特的DDL/DML/QUERY语法,时间是其核心属性。历史意味着时间,意味着快照Snapshot。 我们以一个DDL和一套DML示例说明Temporal Table的原理,DDL定义PK是可选的,下面的示例我们以不定义PK的为例进行说明: DDL 示例CREATE TABLE Emp ENo INTEGER, Sys_Start TIMESTAMP(12) GENERATED ALWAYS AS ROW Start, Sys_end TIMESTAMP(12) GENERATED ALWAYS AS ROW END, EName VARCHAR(30), PERIOD FOR SYSTEM_TIME (Sys_Start,Sys_end) ) WITH SYSTEM VERSIONINGDML 示例INSERTINSERT INTO Emp (ENo, EName) VALUES (22217, 'Joe')![]() 说明: 其中Sys_Start和Sys_End是数据库系统默认填充的。 UPDATEUPDATE Emp SET EName = 'Tom' WHERE ENo = 22217![]() 说明: 假设是在 2012-02-03 10:00:00 执行的UPDATE,执行之后上一个值"Joe"的Sys_End值由9999-12-31 23:59:59 变成了 2012-02-03 10:00:00, 也就是下一个值"Tom"生效的开始时间。可见我们执行的是UPDATE但是数据库里面会存在两条数据,数据值和有效期不同,也就是版本不同。 DELETE (假设执行DELETE之前的表内容如下)![]() ![]() 说明: 假设我们是在2012-06-01 00:00:00执行的DELETE,则Sys_End值由9999-12-31 23:59:59 变成了 2012-06-01 00:00:00, 也就是在执行DELETE时候没有真正的删除符合条件的行,而是系统将符合条件的行的Sys_end修改为执行DELETE的操作时间。标识数据的有效期到DELETE执行那一刻为止。 SELECTSELECT ENo,EName,Sys_Start,Sys_End FROM Emp FOR SYSTEM_TIME AS OF TIMESTAMP '2011-01-02 00:00:00'说明: 这个查询会返回所有Sys_Start 2011-01-02 00:00:00 的记录。 SQLServer Temporal Table 示例DDLCREATE TABLE Department ( DeptID int NOT NULL PRIMARY KEY CLUSTERED , DeptName varchar(50) NOT NULL , ManagerID INT NULL , ParentDeptID int NULL , SysStartTime datetime2 GENERATED ALWAYS AS ROW Start NOT NULL , SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL , PERIOD FOR SYSTEM_TIME (SysStartTime,SysEndTime) ) WITH (SYSTEM_VERSIONING = ON);执行上面的语句,在数据库会创建当前表和历史表,如下图: ![]() Department 显示是有版本控制的,历史表是默认的名字,我也可以指定名字如:SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.DepartmentHistory)。 DMLINSERT - 插入列不包含SysStartTime和SysEndTime列INSERT INTO [dbo].[Department]([DeptID] ,[DeptName] ,[ManagerID] ,[ParentDeptID]) VALUES(10, 'Marketing', 101, 1);执行之后我们分别查询当前表和历史表,如下图: ![]() 我们第一条INSERT语句数据值的有效时间是操作那一刻2018-06-06 05:50:20.7913985 到永远 9999-12-31 23:59:59.9999999,但这时刻历史表还没有任何信息。我们接下来进行更新操作。 UPDATEUPDATE [dbo].[Department] SET [ManagerID] = 501 WHERE [DeptID] = 10执行之后当前表信息会更新并在历史表里面产生一条历史信息,如下:![]() 注意当前表的SysStartTime意见发生了变化,历史表产生了一条记录,SyStartTIme是原当前表记录的SysStartTime,SysEndTime是当前表记录的SystemStartTime。我们再更新一次: UPDATE [dbo].[Department] SET [ManagerID] = 201 WHERE [DeptID] = 10![]() 到这里我们了解到SQLServer里面关于Temporal Table的逻辑是有当前表和历史表来存储数据,并且数据库内部以StartTime和EndTime的方式管理数据的版本。 SELECT SELECT [DeptID], [DeptName], [SysStartTime],[SysEndTime] FROM [dbo].[Department] FOR SYSTEM_TIME AS OF '2018-06-06 05:50:21.0000000' ;![]() SELECT语句查询的是Department的表,实际返回的数据是从历史表里面查询出来的,查询的底层逻辑就是 SysStartTime '2018-06-06 05:50:21.0000000' 。 Apache Flink Temporal Table我们不止一次的提到Apache Flink遵循ANSI-SQL标准,Apache Flink中Temporal Table的概念也源于ANSI-2011的标准语义,但目前的实现在语法层面和ANSI-SQL略有差别,上面看到ANSI-2011中使用FOR SYSTEM_TIME AS OF的语法,目前Apache Flink中使用 LATERAL TABLE(TemporalTableFunction)的语法。这一点后续需要推动社区进行改进。 为啥需要 Temporal Table我们以具体的查询示例来说明为啥需要Temporal Table,假设我们有一张实时变化的汇率表(RatesHistory),如下:rowtime(ts) currency(pk) rate 09:00:00 US Dollar 102 09:00:00 Euro 114 09:00:00 Yen 1 10:45:00 Euro 116 11:15:00 Euro 119 11:49:00 Pounds 108 RatesHistory代表了Yen汇率(Yen汇率为1),是不断变化的Append only的汇率表。例如,Euro兑Yen汇率从09:00至10:45的汇率为114。从10点45分到11点15分是116。 假设我们想在10:58输出所有当前汇率,我们需要以下SQL查询来计算结果表: SELECT * FROM RatesHistory AS r WHERE r.rowtime = ( SELECT MAX(rowtime) FROM RatesHistory AS r2 WHERE r2.currency = r.currency AND r2.rowtime |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |